// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

import { network } from "./network";
import { getChildByName } from "./util";
import { PlayerInfo } from "./playerInfo";
import { MoviePrefab } from "./moviePrefab";
import loginPb = require('./Protobuf/loginPb');
import lockStepPb = require('./Protobuf/lockStepPb');
import { PbCmd } from "./Protobuf/protoMappings";
import { cmd } from "./cmdClient";

const { ccclass, property } = cc._decorator;


@ccclass
export class Main extends cc.Component {
    public static instance: Main = null;
    @property(cc.String)
    private ip: string = "127.0.0.1"
    private port: number = 9202;
    @property(cc.Prefab)
    private moviePrefab: cc.Prefab = null;
    private movieParent: cc.Node = null;
    public isMatching = false;
    private loadingGameSceneCount: number = 0;
    private lastUpdateTime: number = 0;
    onLoad() {
        Main.instance = this;
        this.movieParent = getChildByName(this.node, "match/scroll").children[0].children[0];
    }

    start() {
        network.onOpen(this._svr_onOpen, this);
        network.onClose(this._svr_onClose, this);
        if (!network.isConnected()) {
            // 先显示登录界面
            getChildByName(this.node, "login").active = true;
        } else {
            this._registerMsgHandler();
            getChildByName(this.node, "match").active = true;
            getChildByName(this.node, "match/name").getComponent(cc.Label).string = PlayerInfo.nickname;
            // network.sendMsg(cmd.gate_main_getMovieList);
        }
    }


    // 服务器连接成功
    private _svr_onOpen() {
        console.log("服务器回调执行，开始进行登录验证");
        // 连接服务器成功，注册消息处理函数
        network.addHandler(PbCmd.login_auth_s2c, this._onLoginAuthS2C, this);
        // 尝试登录验证
        this._loginAuth();
    }

    private _registerMsgHandler() {
        network.addHandler(PbCmd.lock_step_match_s2c, this._onLockStepMatchS2C, this);
        network.addHandler(PbCmd.lock_step_fight_start_s2c, this._onLockStepFightStartS2C, this);
        network.addHandler(PbCmd.lock_step_match_success_s2c, this._onLockStepMatchSucessS2C, this);

        
        // network.addHandler(cmd.gate_main_getMovieList, this._svr_getMovieListBack, this);
        // network.addHandler(cmd.gate_main_getMovieData, this._svr_getMovieDataBack, this);
    }

    // 登录验证返回
    private _onLoginAuthS2C(message: loginPb.Game.login_auth_s2c) {
        let errCode = message.code;
        if (errCode != 0) {
            console.log(`登录验证失败，错误码${errCode}`);
            network.closeNetwork("登录验证失败");
        }
        else {
            let roleList = message.roleList;
            // 默认选择第一个角色
            let firstRole = roleList[0];
            PlayerInfo.nickname = firstRole.name;
            PlayerInfo.roleId = firstRole.id;
            network.addHandler(PbCmd.login_choose_role_s2c, this._onLoginChooseRoleS2C, this);
            console.log(`登录验证成功, 请求服务器选择默认第一个角色`);
            let chooseRoleMsg = loginPb.Game.login_choose_role_c2s.create();
            chooseRoleMsg.roleId = firstRole.id;
            network.sendMsg(chooseRoleMsg);
        }
    }
    // 登录选角返回
    private _onLoginChooseRoleS2C(message: loginPb.Game.login_choose_role_s2c) {
        let errCode = message.code;
        if (errCode != 0) {
            console.log(`选角失败，错误码${errCode}`);
            network.closeNetwork("选角失败");
        }
        else {
            console.log(`选角成功 角色id：${message.roleId}`);
            network.addHandler(cmd.login_finish, this._onLoginFinish, this);
            network.addMsgCache(cmd.login_finish);
        }
        
    }

    // 登录完成
    private _onLoginFinish() {
        // 注册消息处理函数
        this._registerMsgHandler();
        getChildByName(this.node, "connectSvr").active = false;
        getChildByName(this.node, "match").active = true;
        getChildByName(this.node, "match/name").getComponent(cc.Label).string = PlayerInfo.nickname ;
        // network.sendMsg(cmd.gate_main_getMovieList);

    }

    // 服务器断开连接
    private _svr_onClose() {
        console.log("server close main")
        getChildByName(this.node, "svrClose").active = true;
    }

    private btn_reloadScene() {
        cc.director.loadScene("test");
    }

    private btn_enterGame() {
        // 设置页面为连接服务器当中
        getChildByName(this.node, "login").active = false;
        getChildByName(this.node, "connectSvr").active = true;
        // 点击进入游戏先连接服务器
        network.connect(this.ip, this.port);
    }

    private _loginAuth() {
        console.log("登录验证 ...");
        let nickname = getChildByName(this.node, "login/nameEdit").getComponent(cc.EditBox).string.trim();
        // 然后发送登录验证信息
        let loginMessage = loginPb.Game.login_auth_c2s.create();
        loginMessage.uname = nickname;
        console.log("发送登录验证信息 ...");        
        network.sendMsg(loginMessage);
    }

    private btn_matchOrNot() {
        let MatchMessage = lockStepPb.Game.lock_step_match_c2s.create();
        network.sendMsg(MatchMessage);
    }
    private _onLockStepMatchS2C(message: lockStepPb.Game.lock_step_match_s2c) {
        console.log("收到匹配消息返回 ..."); 
        let btnMatch = getChildByName(this.node, "match/btn_match");
        this.isMatching = message.code == 0;
        if (this.isMatching) {
            btnMatch.children[0].children[0].getComponent(cc.Label).string = "取消匹配";
            btnMatch.children[1].active = true;
        } else {
            btnMatch.children[0].children[0].getComponent(cc.Label).string = "匹配";
            btnMatch.children[1].active = false;
        }
    }

    private _onLockStepMatchSucessS2C(message: lockStepPb.Game.lock_step_match_success_s2c) {
        console.log("收到匹配成功消息返回 ... 切换到加载游戏场景页面"); 

        getChildByName(this.node, "match").active = false;
        getChildByName(this.node, "loadingGameScene").active = true;
        this.loadingGameSceneCount = 3; // 倒计时3秒
        let countDownNumLabel = getChildByName(this.node, "loadingGameScene/countDownNumLabel");
        countDownNumLabel.getComponent(cc.Label).string = this.loadingGameSceneCount.toString();
        
    }

    private _onLockStepFightStartS2C(message: lockStepPb.Game.lock_step_fight_start_s2c) {
        PlayerInfo.startTime = message.startTime.toNumber();
        PlayerInfo.randomSeed = message.randomSeed;
        PlayerInfo.startGameData = message.unitInfos;
        PlayerInfo.isMovie = false;
        getChildByName(this.node, "loadingGameScene").active = false;
        cc.director.loadScene("game");
    }

    update() {
        let nowTime = Math.floor(Date.now() / 1000);
        if (nowTime - this.lastUpdateTime > 1)  { // 更新秒
            this.lastUpdateTime = nowTime;
            if (this.loadingGameSceneCount > 0) {
                this.loadingGameSceneCount--;
                let countDownNumLabel = getChildByName(this.node, "loadingGameScene/countDownNumLabel");
                if (this.loadingGameSceneCount == 0) {
                    // 通知客户端加载完成游戏场景
                    let changeSceneFinishMsg = lockStepPb.Game.lock_step_change_scene_finish_c2s.create();
                    countDownNumLabel.getComponent(cc.Label).string = "";
                    let countDownLabel = getChildByName(this.node, "loadingGameScene/countDownLabel");
                    countDownLabel.getComponent(cc.Label).string = "等待其他玩家加载完成...";
                    network.sendMsg(changeSceneFinishMsg);
                }
                else {
                    countDownNumLabel.getComponent(cc.Label).string = this.loadingGameSceneCount.toString();
                }
                
            }
        }
        network.readMsg();
    }

    private _svr_getMovieListBack(msg: { "list": any[] }) {
        for (let one of msg.list) {
            let node = cc.instantiate(this.moviePrefab);
            node.parent = this.movieParent;
            node.getComponent(MoviePrefab).init(one);
        }
    }
    private _svr_getMovieDataBack(msg: { "id": number, "data": any }) {
        if (!msg.data) {
            this.movieParent.getChildByName(msg.id.toString()).destroy();
            return;
        }
        PlayerInfo.isMovie = true;
        PlayerInfo.startGameData = msg.data.startData;
        PlayerInfo.frames = msg.data.frames;
        cc.director.loadScene("game");
    }

    onDestroy() {
        network.removeThisHandlers(this);
    }
}

